/*
  获取access_token:
    全局唯一的接口调用凭据，今后使用微信的接口基本上都需要携带上这个参数
     2小时需要更新一次，提前5分钟刷新

    请求地址：
      https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    请求方式：
      GET

    设计思路：
      首先发送请求获取凭据，保存为一个唯一的文件
      然后后面请求先去本地文件读取凭据
        判断凭据是否过期
          如果没有过期，直接使用
          如果过期了，重新发送请求获取凭据，保存下来覆盖之前的文件

    总结：
      先去本地查看有没有指定文件（readAccessToken）
        如果有（之前请求过凭据）
          判断凭据是否过期(isValidAccessToken)
            如果没有过期，直接使用
            如果过期了，重新发送请求获取凭据，保存下来覆盖之前的文件(getAccessToken、saveAccessToken)
        如果没有（之前都没有请求过凭据）
         发送请求获取凭据，保存为一个唯一的文件

 */
//引入配置对象
const {appID, appsecret} = require('../config');
//引入发送http请求的库
const rp = require('request-promise-native');
//引入fs模块（保存文件）
const {readFile, writeFile} = require('fs');
//引入menu模块（自定义菜单）
const menu = require('./menu')

class Wechat {
    //请求access-token
    getAccessToken() {
        //定义请求地址
        const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
        /*所以异步操作都应该包装一层 promise 对象，让这个也不操作执行完毕之后，再去执行后面的代码*/
        return new Promise((resolve,reject)=>{
            rp({method:'GET',json:true,url}).then(res=>{
                //重新赋值凭据的过期时间：当前时间+(7200-5分钟)*1000
                res.expires_in=Date.now()+(res.expires_in-300)*1000;
                console.log('res')
                resolve(res);
            })
        }).catch(err=>{
            reject('getAccessToken方法出了问题：'+err);
        })
    }
    //读取access-token
    readAccessToken(){
        return new Promise((resolve,reject)=>{
            readFile('accessToken.txt',(err,data)=>{
                if(!err){
                    //将读取的 Buffer 数据转化为 json 数据
                    data=data.toString()
                    data=data?JSON.parse(data):{};
                    resolve(data)
                }else {
                    reject('readAccessToken方法出了问题：'+err);
                }
            })
        })
    }

    //保存access-token
    saveAccessToken(data){
        data=JSON.stringify(data);
        return new Promise((resolve,reject)=>{
        //将凭据保持为一个文件
            writeFile('accessToken.txt',data,err => {
                if (!err){
                    //写入成功
                    resolve();
                }else {
                    // 写入失败
                    reject('saveAccessToken方法出了问题：'+err);
                }
            })
        })
    }

    // access-token 是否过期
    isValidAccessToken(data){
        // 判断是否过期
        if(!data||!data.access_token||!data.expires_in)return false
        //保存的时间大于当前的时间没有过期否则过期了
        return  data.expires_in>Date.now();
    }

    //判断方法
     fentchAccessToken(){
         if(this.access_token&&this.expires_in&&this.isValidAccessToken(this)){
             console.log('获取access-token')
             return Promise.resolve({
                 access_token:this.access_token,
                 expires_in:this.expires_in
             })
         }
        return this.readAccessToken().then(async res=>{
            // 判断凭据是否过期
            if(this.isValidAccessToken(res)){
            // 没有过期,直接使用
                return Promise.resolve(res);
            }else {
                //重新发送请求获取凭据
                const data=await this.getAccessToken()
                //保存下来
                await this.saveAccessToken(data);
                //返回请求的凭据
                return Promise.resolve(data);
            }
        }).catch(async err=>{
            console.log(err)
            //重新发送请求获取凭据
            const data=await this.getAccessToken()
            //保存下来
            await this.saveAccessToken(data);
            //返回请求的凭据
            return Promise.resolve(data);
        }).then(res => {
            console.log(res)
            //将其请求回来的凭据和过期时间挂载到this上
            this.access_token = res.access_token;
            this.expires_in = res.expires_in;
            //指定fetchAccessToken方法返回值
            return Promise.resolve(res);
        })
    };
    // 自定义菜单 https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
    /*
    * 用来创建自定义菜单
    * */
    createMenu(menu){
        return new Promise( async (resolve,reject)=>{
            try{
                // 获取access_token;
                const data = await this.fentchAccessToken();
                const url = `https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${data.access_token}`;
                //发送请求
                const result = await rp({method:'POST',url,json:true,body:menu})
                resolve(result)
            }catch (e){
                reject('createMenu方法出了问题：'+e);
            }
        })

    }
    /*
    * 用来删除自定义菜单
    * */
    deletemenu(){
        return new Promise(async (resolve,reject)=>{
            try{
            //获取access_token
                const data = await this.fentchAccessToken();
                const url = `https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=${data.access_token}`
                const result = await rp({method:'GET',url,json:true})
                resolve(result)
            }catch (e){
                reject('deletemenu方法出了问题：'+e);
            }
        })
    }
};

//创建自定义菜单之前需要先删除自定义菜单
(async ()=>{
    const w = new Wechat()
    let result =await w.deletemenu()
    console.log(result)
    result=await w.createMenu(menu)
    console.log(result)
})()